package com.into.common.csv.engine;

import java.util.Collection;

import org.apache.commons.beanutils.PropertyUtils;

import com.into.common.csv.CSVConverter;
import com.into.common.csv.CSVField;
import com.into.common.csv.CSVFieldsDefiner;

/**
 * Outputs a CSV from {@link Object} objects
 * 
 * @author Zied Hamdi
 * 
 */
public class CSVWriter {
	protected String separator;

	public CSVWriter(String separator) {
		this.separator = separator;
	}

	public String toCSV(CSVFieldsDefiner fieldsDefiner,
			Collection<? extends Object> collection) throws Exception {
		StringBuffer toReturn = new StringBuffer();
		for (Object serializable : collection) {
			toCSV(fieldsDefiner, serializable, toReturn);
			toReturn.append('\n');
		}
		return toReturn.toString();
	}

	@SuppressWarnings("unchecked")
	public void toCSV(CSVFieldsDefiner fieldsDefiner, Object Object,
			StringBuffer out) throws Exception {
		CSVField<?>[] fields = fieldsDefiner.getCSVFields(Object);
		for (int i = 0; i < fields.length; i++) {
			CSVField field = fields[i];
			CSVConverter converter = field.getConverter();
			if (field.isOnlyCSV()) {
				if (converter != null)
					out.append(converter.toString(Object));
			} else {
				out.append(converter.toString(getValue(Object, field)));
			}

			if (i < fields.length - 1)
				out.append(separator);
		}
	}

	@SuppressWarnings("unchecked")
	protected <T> T getValue(Object Object, CSVField<T> field) {
		try {
			return (T) PropertyUtils.getProperty(Object, field.getName());
		} catch (Exception ex) {
			throw new IllegalStateException("Can't access " + Object.getClass()
					+ "'s field " + field.getName(), ex);
		}
	}
}
